package com.marvels.financial.loan.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.marvels.common.constants.PageConstant;
import com.marvels.common.constants.PayContants;
import com.marvels.common.constants.RedisKeyConstant;
import com.marvels.common.dto.UserDTO;
import com.marvels.common.dto.pay.McfePaymentUserBindCard;
import com.marvels.common.exception.MarvelsBusinessException;
import com.marvels.common.utils.CacheUtils;
import com.marvels.common.utils.CommonProperties;
import com.marvels.common.utils.GenerateReqNoUtils;
import com.marvels.common.utils.MarvelsLogUtil;
import com.marvels.common.utils.StringUtils;
import com.marvels.financial.loan.dao.McfeCustomerLoanContractDao;
import com.marvels.financial.loan.dao.McfePaymentWithholdDetailDao;
import com.marvels.financial.loan.dao.McfeRepaymentFlowDao;
import com.marvels.financial.loan.dao.McfeWithholdManualDao;
import com.marvels.financial.loan.dao.McfeWithholdingBankLimitDao;
import com.marvels.financial.loan.dto.ExtensionFunctionConditionDTO;
import com.marvels.financial.loan.dto.HandWithholdConditionDTO;
import com.marvels.financial.loan.dto.HandWithholdListDTO;
import com.marvels.financial.loan.dto.HandleWithholdResultDTO;
import com.marvels.financial.loan.dto.LoanAfterInfoDTO;
import com.marvels.financial.loan.dto.McfeCustomerLoanContractDTO;
import com.marvels.financial.loan.dto.McfePaymentWithholdDTO;
import com.marvels.financial.loan.dto.McfePaymentWithholdDetailDTO;
import com.marvels.financial.loan.dto.McfeRepaymentFlowDTO;
import com.marvels.financial.loan.dto.McfeWithholdManualDTO;
import com.marvels.financial.loan.dto.McfeWithholdingBankLimitDTO;
import com.marvels.financial.loan.service.ExtensionFunctionApi;
import com.marvels.financial.loan.service.HandleWithholdApi;
import com.marvels.financial.loan.service.WithholdPaymentApi;
import com.marvels.financial.pay.dao.McfePaymentUserBindCardMapper;
import com.marvels.financial.pay.dto.McfePaymentUserBindCardCondition;

import cn.hutool.core.util.StrUtil;

@Service
public class HandleWithholdImpl implements HandleWithholdApi {

	@Autowired
	private McfeCustomerLoanContractDao dao;

	@Autowired
	private McfeWithholdManualDao manualDao;


	@Autowired
	private WithholdPaymentApi withholdPaymentApi;


	@Autowired
	private McfeWithholdingBankLimitDao limitDao;
	
	@Autowired
	private ExtensionFunctionApi extensionFunctionApi;

	@Autowired
	private McfeRepaymentFlowDao flowDao;
	
	@Autowired
	private McfeCustomerLoanContractDao mcfeCustomerLoanContractDao;
	
	@Autowired
	private McfePaymentWithholdDetailDao detailDao;
	
	@Autowired
	private McfePaymentUserBindCardMapper mcfePaymentUserBindCardMapper;
	
	@Override
	public Page<HandWithholdListDTO> applyList(HandWithholdConditionDTO dto) {
		int pageSize = dto.getPageSize();
		int pageNum = dto.getPageNum();
		if (pageSize < 1) {
			pageSize = PageConstant.PAGESIZE;
		}
		if (pageNum < 1) {
			pageNum = PageConstant.CURRPAGE;
		}
		PageHelper.startPage(pageNum, pageSize);
		
		Page<HandWithholdListDTO> handWithholdList = null;
		
		if(org.apache.commons.lang3.StringUtils.equalsIgnoreCase("Y", CommonProperties.getNewRepaymentFlag())) {
			handWithholdList = dao.newSelectWithholdApplyList(dto);
		}else {
			handWithholdList = dao.selectWithholdApplyList(dto);
		}

		return handWithholdList;
	}

	@Override
	public  void handleWithholeApply(HandWithholdConditionDTO dto) throws MarvelsBusinessException {
		String type = dto.getType();
		if(StringUtils.isEmpty(type)){
			throw new MarvelsBusinessException("代扣款项类目为空");
		}
		if(StringUtils.isEmpty(dto.getPaymentBankId())){
			throw new MarvelsBusinessException("所选银行卡为空");
		}
		if(StringUtils.isEmpty(dto.getPaymentChannel())){
			throw new MarvelsBusinessException("代扣渠道为空");
		}
		int extensionDay = 0;
		String loanId = dto.getLoanId();
		Page<HandWithholdListDTO> contractDtoList = dao.selectWithholdApplyList(dto);
		if (null == contractDtoList || contractDtoList.size() < 1) {
			throw new MarvelsBusinessException("合同信息不存在");
		}
		HandWithholdListDTO contractDto = contractDtoList.get(0);
		if(type.equals("1")){
			if (dto.getWithholdAmout().compareTo(new BigDecimal("0")) < 1) {
				throw new MarvelsBusinessException("请输入代扣金额");
			}
			if (dto.getWithholdAmout().compareTo(contractDto.getPaymentTotal()) > 0) {
				throw new MarvelsBusinessException("代扣金额不能大于应还总额");
			}
		}else{
			String extensionType = dto.getExtensionType();
			if(StringUtils.isEmpty(extensionType)){
				throw new MarvelsBusinessException("展期类别为空");
			}
			ExtensionFunctionConditionDTO conditionDTO=new ExtensionFunctionConditionDTO();
			conditionDTO.setLoanId(loanId);
			conditionDTO.setType(extensionType);
			conditionDTO=extensionFunctionApi.selectExtensionInfo(conditionDTO);
			extensionDay = conditionDTO.getDay();
			dto.setWithholdAmout(conditionDTO.getAmount());

		}
		
		if ("2".equals(contractDto.getStatus()) || "3".equals(contractDto.getStatus())
				|| "10".equals(contractDto.getStatus())) {
			throw new MarvelsBusinessException("进件不处于还款状态");
		}
		
		McfePaymentUserBindCardCondition condition = new McfePaymentUserBindCardCondition();
		condition.setIdno(contractDto.getCustCardNo());
		condition.setId(dto.getPaymentBankId());
		condition.setStatus("BIND_SUCCESS");
		condition.setUnbindStatus("0");
		condition.setChannel(dto.getPaymentChannel());
		McfePaymentUserBindCard paymentUserBindCard = mcfePaymentUserBindCardMapper.selectByCondition(condition);
		if(paymentUserBindCard ==null){
			throw new MarvelsBusinessException("该银行卡不存在");
		}
		// 加锁 避免重复插入数据
		String key = RedisKeyConstant.HAND_PAYMENT_WITHHOLD + loanId;
		boolean isNotLock = false;
		try {
			isNotLock = CacheUtils.isNotLock(key, loanId);
			if (isNotLock) {
				// 先将这个key设置过期时间
				CacheUtils.setExpire(key, 60);
				// 判断还款计划对应的进件是否有处在正在冲账中的流水
				McfeRepaymentFlowDTO flowDTO = flowDao.selectDealingByLoanId(dto.getLoanId());
				if (flowDTO != null) {
					MarvelsLogUtil.getInstance().info(">>>>>>>>>>loanId:" + dto.getLoanId() + ",有处在冲账中或未冲账的流水");
					throw new MarvelsBusinessException("存在未冲账的流水,请稍候再试");
				}
				McfePaymentWithholdDetailDTO detailDTO = detailDao.selectTradingByLoanId(loanId);
				if (detailDTO != null) {
					MarvelsLogUtil.getInstance()
					.info(">>>>>>>>>>loanId:" + loanId + ",存在处理中的代扣");
					throw new MarvelsBusinessException("存在处理中的代扣请稍候再试");
				}
				// 查看是否存在申请中的数据
				McfeWithholdManualDTO mcfeWithholdManualDTO = new McfeWithholdManualDTO();
				mcfeWithholdManualDTO.setLoanId(dto.getLoanId());
				McfeWithholdManualDTO manualDTO = manualDao.selectWithholdManual(mcfeWithholdManualDTO);
				if (null != manualDTO && "0".equals(manualDTO.getStatus())) {
					throw new MarvelsBusinessException("存在待审核的申请");
				}
				// 持久化
				UserDTO user = CacheUtils.getCacheUser();
				mcfeWithholdManualDTO = new McfeWithholdManualDTO();
				mcfeWithholdManualDTO.setAmount(dto.getWithholdAmout());
				mcfeWithholdManualDTO.setBankCardNo(paymentUserBindCard.getBankCardNo());
				// mcfeWithholdManualDTO.setBankHeadLink(contractDto.getPaymentBankHead());
				mcfeWithholdManualDTO.setBankName(paymentUserBindCard.getBankName());
				mcfeWithholdManualDTO.setConsultingFee(contractDto.getConsultingFee());
				mcfeWithholdManualDTO.setCreatedBy(user.getUserCode());
				mcfeWithholdManualDTO.setCreatedDate(new Date());
				mcfeWithholdManualDTO.setCustCardNo(contractDto.getCustCardNo());
				mcfeWithholdManualDTO.setCustName(contractDto.getCustName());
				mcfeWithholdManualDTO.setDelqDays(contractDto.getDelqDays());
				mcfeWithholdManualDTO.setFundCode(contractDto.getFundCode());
				mcfeWithholdManualDTO.setInterest(contractDto.getInterest());
				mcfeWithholdManualDTO.setLateFee(contractDto.getLateFee());
				mcfeWithholdManualDTO.setLoanId(contractDto.getLoanId());
				mcfeWithholdManualDTO.setManagementFee(contractDto.getManagementFee());
				mcfeWithholdManualDTO.setMobile(contractDto.getMobile());
				mcfeWithholdManualDTO.setReqChannel(dto.getPaymentChannel());
				mcfeWithholdManualDTO.setPayType(1);// 还款类型: 1-代扣;2-提前结清
				mcfeWithholdManualDTO.setPenaltyFee(contractDto.getPenaltyFee());
				mcfeWithholdManualDTO.setPrincipal(contractDto.getPrincipal());
				mcfeWithholdManualDTO.setReqChannel(dto.getPaymentChannel());
				mcfeWithholdManualDTO.setStatus("0");
				mcfeWithholdManualDTO.setType(Integer.valueOf(type));
				mcfeWithholdManualDTO.setUpdatedBy(user.getUserCode());
				mcfeWithholdManualDTO.setUpdatedDate(new Date());
				mcfeWithholdManualDTO.setTransctionSeq(GenerateReqNoUtils.transctionReq("TX"));
				mcfeWithholdManualDTO.setExtensionDay(extensionDay);
				mcfeWithholdManualDTO.setExtensionType(dto.getExtensionType());
				int insertCount = manualDao.insertSelective(mcfeWithholdManualDTO);
				if (insertCount < 1) {
					throw new MarvelsBusinessException("持久化手动代扣审核信息异常");
				}
			}
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error(">>>>>loanId:" + loanId + ",代还款审核通过异常:", e);
			throw new MarvelsBusinessException(e.getMessage());
		} finally {
			if (!CacheUtils.isNotLock(key, loanId)) {// 如果是锁住的将所释放
				CacheUtils.del(key);
			}
		}
	}

	@Override
	public Page<HandWithholdListDTO> handleWithholeReviewList(HandWithholdConditionDTO dto)
			throws MarvelsBusinessException {

		int pageSize = dto.getPageSize();
		int pageNum = dto.getPageNum();
		if (pageSize < 1) {
			pageSize = PageConstant.PAGESIZE;
		}
		if (pageNum < 1) {
			pageNum = PageConstant.CURRPAGE;
		}
		PageHelper.startPage(pageNum, pageSize);
		dto.setApplyStatus("0");// 待审核
		//转换渠道名称
		Page<HandWithholdListDTO> list = manualDao.selectWithholdReviewList(dto);
		for (HandWithholdListDTO handWithholdListDTO : list) {
			PayContants payContants = PayContants.getPayEnumByCode(handWithholdListDTO.getPaymentChannel());
			if(payContants != null){
				handWithholdListDTO.setPaymentChannel(payContants.getMessage());
			}
		}
		return list;
	}

	@Override
	public void handleWithholeReviewRefuse(HandWithholdConditionDTO dto) throws MarvelsBusinessException {
		// 查看是否存在申请中的数据
		McfeWithholdManualDTO mcfeWithholdManualDTO = new McfeWithholdManualDTO();
		mcfeWithholdManualDTO.setLoanId(dto.getLoanId());
		McfeWithholdManualDTO manualDTO = manualDao.selectWithholdManual(mcfeWithholdManualDTO);
		if (null == manualDTO) {
			throw new MarvelsBusinessException("申请信息不存在");
		}
		if (!"0".equals(manualDTO.getStatus())) {
			throw new MarvelsBusinessException("申请信息不处于待审核状态");
		}
		// 更新审核状态
		UserDTO user = CacheUtils.getCacheUser();
		McfeWithholdManualDTO withholdManualDTO = new McfeWithholdManualDTO();
		withholdManualDTO.setStatus("2");// 拒绝
		withholdManualDTO.setUpdatedBy(user.getUserName());
		withholdManualDTO.setUpdatedDate(new Date());
		withholdManualDTO.setLoanId(dto.getLoanId());
		int updateCount = manualDao.updateWithholdManual(withholdManualDTO);
		if (updateCount < 1) {
			throw new MarvelsBusinessException("更新审核状态失败");
		}
	}
	
	
	/**
	 * 
	* @Title: handleWithholeReviewAdopt 
	* @Description: 核心后台-手动还款逻辑 
	* @param dto
	* @throws MarvelsBusinessException       
	* @author 李瑶
	* @date 2018年10月20日 下午2:01:43
	 */
	@Override
	public  void handleWithholeApprove(HandWithholdConditionDTO dto) throws MarvelsBusinessException {
		McfeWithholdManualDTO mcfeWithholdManualDTO = new McfeWithholdManualDTO();
		mcfeWithholdManualDTO.setLoanId(dto.getLoanId());
		McfeWithholdManualDTO manualDTO = manualDao.selectWithholdManual(mcfeWithholdManualDTO);
		if (null == manualDTO) {
			throw new MarvelsBusinessException("申请信息不存在");
		}
		if (!"0".equals(manualDTO.getStatus())) {
			throw new MarvelsBusinessException("申请信息不处于待审核状态");
		}
		int type = manualDTO.getType();
		if(type == 1){
			//还款代扣通过
			handleWithholeReviewAdopt(manualDTO);
		}else{
			//展期费代扣通过
			extensionWithholeReviewAdopt(manualDTO);
		}
		
	}

	/**
	 * 
	* @Title: handleWithholeReviewAdopt 
	* @Description: 核心后台-手动代扣逻辑 
	* @param dto
	* @throws MarvelsBusinessException       
	* @author 李瑶
	* @date 2018年10月20日 下午2:01:43
	 */
	@Override
	public  void handleWithholeReviewAdopt(McfeWithholdManualDTO manualDTO) throws MarvelsBusinessException {
		
		if (null == manualDTO) {
			throw new MarvelsBusinessException("申请信息不存在");
		}
		if (!"0".equals(manualDTO.getStatus())) {
			throw new MarvelsBusinessException("申请信息不处于待审核状态");
		}
		McfePaymentWithholdDTO paymentWithholdDTO=new McfePaymentWithholdDTO();
		paymentWithholdDTO.setLoanId(manualDTO.getLoanId());
		paymentWithholdDTO.setRepayStyle("6");//代扣流水还款类型: 1-自动代扣;2-当前还款;3-提前结清;4-主动还款; 5-下期还款; 6-手动代扣 ; 9-支付宝还款 10-支付宝提前结清
		paymentWithholdDTO.setPayType(1);//还款类型 1 - 还款  2 提前结清
		paymentWithholdDTO.setFlowPayType("1");
		paymentWithholdDTO.setTransctionSeq(manualDTO.getTransctionSeq());
		paymentWithholdDTO.setAmount(manualDTO.getAmount());
		paymentWithholdDTO.setBankHeadLink(manualDTO.getBankHeadLink());
		paymentWithholdDTO.setBankCardNo(manualDTO.getBankCardNo());
		paymentWithholdDTO.setBankName(manualDTO.getBankName());
		paymentWithholdDTO.setCustCardNo(manualDTO.getCustCardNo());
		paymentWithholdDTO.setReqChannel(manualDTO.getReqChannel());
		paymentWithholdDTO.setWithholdCategory("1");//代扣类别   1扣还款金额    2 扣展期
		//代扣逻辑
		withholdPaymentApi.withholdCommonDeal(paymentWithholdDTO);
		// 更新审核状态
		UserDTO user=CacheUtils.getCacheUser();
		McfeWithholdManualDTO withholdManualDTO = new McfeWithholdManualDTO();
		withholdManualDTO.setStatus("1");// 通过
		withholdManualDTO.setUpdatedBy(user.getUserCode());
		withholdManualDTO.setUpdatedDate(new Date());
		withholdManualDTO.setLoanId(manualDTO.getLoanId());
		int updateCount = manualDao.updateWithholdManual(withholdManualDTO);
		if (updateCount < 1) {
			throw new MarvelsBusinessException("更新审核状态失败");
		}
	}
	
	
	/**
	 * 
	* @Title: extensionWithholeReviewAdopt 
	* @Description:核心后台-展期费用审核通过  
	* @param dto
	* @throws MarvelsBusinessException       
	* @author 李瑶
	* @date 2018年10月31日 下午8:37:22
	 */
	@Override
	public  void extensionWithholeReviewAdopt(McfeWithholdManualDTO manualDTO) throws MarvelsBusinessException {
		
		if (null == manualDTO) {
			throw new MarvelsBusinessException("申请信息不存在");
		}
		if (!"0".equals(manualDTO.getStatus())) {
			throw new MarvelsBusinessException("申请信息不处于待审核状态");
		}
		McfePaymentWithholdDTO paymentWithholdDTO=new McfePaymentWithholdDTO();		
		paymentWithholdDTO.setLoanId(manualDTO.getLoanId());
		paymentWithholdDTO.setFlowPayType("1");
		paymentWithholdDTO.setTransctionSeq(manualDTO.getTransctionSeq());
		paymentWithholdDTO.setWithholdCategory("2");//代扣类别   1扣还款金额    2 扣展期
		paymentWithholdDTO.setExtensionDay(manualDTO.getExtensionDay());
		paymentWithholdDTO.setAmount(manualDTO.getAmount());
		McfeCustomerLoanContractDTO contractDTO=mcfeCustomerLoanContractDao.selectContractByLoanId(manualDTO.getLoanId());
		paymentWithholdDTO.setBankHeadLink(manualDTO.getBankHeadLink());
		paymentWithholdDTO.setBankCardNo(manualDTO.getBankCardNo());
		paymentWithholdDTO.setBankName(manualDTO.getBankName());
		paymentWithholdDTO.setCustCardNo(contractDTO.getCustCardNo());
		paymentWithholdDTO.setReqChannel(manualDTO.getReqChannel());
		//代扣逻辑
		withholdPaymentApi.withholdCommonDeal(paymentWithholdDTO);
		// 更新审核状态
		UserDTO user=CacheUtils.getCacheUser();
		McfeWithholdManualDTO withholdManualDTO = new McfeWithholdManualDTO();
		withholdManualDTO.setStatus("1");// 通过
		withholdManualDTO.setUpdatedBy(user.getUserCode());
		withholdManualDTO.setUpdatedDate(new Date());
		withholdManualDTO.setLoanId(manualDTO.getLoanId());
		int updateCount = manualDao.updateWithholdManual(withholdManualDTO);
		if (updateCount < 1) {
			throw new MarvelsBusinessException("更新审核状态失败");
		}
		
		
	}

	/**
	 * 金额拆分
	 * 
	 * @param amount
	 *            要拆分金额
	 * @param bankHeadLink
	 *            总行号
	 * @return
	 */
	@Override
	public BigDecimal[] amountSplit(BigDecimal amount, String bankHeadLink) {
		// 查询总行号限额
		BigDecimal[] decimals = null;
		LoanAfterInfoDTO afterInfoDTO = new LoanAfterInfoDTO();
		afterInfoDTO.setPaymentBankHead(bankHeadLink);
		McfeWithholdingBankLimitDTO lLimitDTO = limitDao.selectWithholdingBankLimitDTO(afterInfoDTO);
		if (null != lLimitDTO && amount.compareTo(new BigDecimal("0")) > 0) {
			int size = 0;
			if (amount.divide(lLimitDTO.getAmountSigLimit())
					.doubleValue() > (amount.divide(lLimitDTO.getAmountSigLimit()).intValue())) {
				size = amount.divide(lLimitDTO.getAmountSigLimit()).intValue() + 1;
			} else {
				size = amount.divide(lLimitDTO.getAmountSigLimit()).intValue();
			}
			decimals = new BigDecimal[size];
			for (int i = 0; i < size; i++) {
				if (i == size - 1) {
					decimals[i] = amount.subtract(lLimitDTO.getAmountSigLimit().multiply(new BigDecimal(size - 1)));
				} else {
					decimals[i] = lLimitDTO.getAmountSigLimit();
				}
			}
		}
		return decimals;
	}

	@Override
	public List<HandleWithholdResultDTO> handleWithholeReviewResult(HandWithholdConditionDTO dto) throws MarvelsBusinessException {
		int pageSize = dto.getPageSize();
		int pageNum = dto.getPageNum();
		if (pageSize < 1) {
			pageSize = PageConstant.PAGESIZE;
		}
		if (pageNum < 1) {
			pageNum = PageConstant.CURRPAGE;
		}
		PageHelper.startPage(pageNum, pageSize);
		//转换渠道名称
		Page<HandleWithholdResultDTO> list = manualDao.selectWithholdResultList(dto);
		for (HandleWithholdResultDTO handelWithholdListDTO : list) {
			PayContants payContants = PayContants.getPayEnumByCode(handelWithholdListDTO.getPaymentChannel());
			if(payContants != null){
				handelWithholdListDTO.setPaymentChannel(payContants.getMessage());
			}
		}
		return list;
	}

	@Override
	public List<Map<String, Object>> queryUserBankList(McfePaymentUserBindCard param)
			throws MarvelsBusinessException {
		if(StrUtil.isEmpty(param.getIdno()) || StrUtil.isEmpty(param.getChannel())){
			throw new MarvelsBusinessException("查询参数为空");
		}
		List<McfePaymentUserBindCard> bankList = mcfePaymentUserBindCardMapper.selectBindSuccessListByIdno(param.getIdno(), param.getChannel());
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		for (McfePaymentUserBindCard mcfePaymentUserBindCard : bankList) {
			Map<String, Object> bank = new HashMap<String, Object>();
			bank.put("id", mcfePaymentUserBindCard.getId());
			bank.put("bankName", mcfePaymentUserBindCard.getBankName());
			bank.put("bankCardNo", mcfePaymentUserBindCard.getBankCardNo());
			bank.put("defaultCard", mcfePaymentUserBindCard.getDefaultCard());
			result.add(bank);
		}
		return result;
	}
	
}
